import fs from 'fs-extra';
import {glob} from 'glob';
import path from 'path';
import {FileInfo, FindPathsOptions} from '../types';
import folderSize from "./folderSize";

export class FileUtil {

  /**
   * 获取文件大小
   */
  public static async getFileSize(filePath: string): Promise<number> {
    try {
      const stats = await fs.stat(filePath);
      return stats.size;
    } catch (error) {
      return 0;
    }
  }

  /**
   * 获取目录大小
   */
  public static async getDirectorySize(dirPath: string): Promise<number> {
    return await folderSize.loose(dirPath);
  }

  /**
   * 检查路径是否应该被排除
   */
  public static shouldExcludePath(filePath: string, excludes: string[] = []): boolean {
    const basename = path.basename(filePath);
    return excludes.some(dir => basename === dir);
  }

  /**
   * 使用glob查找文件和目录路径
   * @param rootPath 根目录路径
   * @param options 选项
   * @returns 匹配的路径数组
   */
  public static async findPaths(rootPath: string, options: FindPathsOptions): Promise<string[]> {
    const {
      depth = 1,
      excludes = [],
      patterns = ['**'],
      fileType = 'all'
    } = options;

    const allPaths: Set<string> = new Set();

    for (const pattern of patterns) {
      const matches = await glob(pattern, {
        cwd: rootPath,
        ignore: excludes,
        maxDepth: depth,
        absolute: true
      });

      // 根据fileType过滤结果
      for (const match of matches) {
        allPaths.add(match);
        try {
          const stats = await fs.stat(match);

          if (
            (fileType === 'file' && stats.isFile()) ||
            (fileType === 'directory' && stats.isDirectory())
          ) {
            allPaths.add(match);
          }
        } catch (error) {
          // 忽略无法访问的文件
          console.error(`无法访问文件: ${match}`, error);
        }
      }
    }

    return Array.from(allPaths);
  }

  /**
   * 获取文件夹子项
   * 只返回基本信息，不递归加载子目录内容
   * @param dirPath 目录路径
   * @returns 子项信息数组
   */
  public static async getDirectoryChildren(dirPath: string): Promise<FileInfo[]> {
    try {
      if (!fs.existsSync(dirPath)) {
        return [];
      }

      const files = await fs.readdir(dirPath);

      const children = await Promise.all(
        files.map(async (file) => {
          const filePath = path.join(dirPath, file);
          try {
            const stats = await fs.stat(filePath);
            const isDirectory = stats.isDirectory();

            const size = isDirectory ? await this.getDirectorySize(filePath) : stats.size;

            // 只返回基本信息，不递归加载子目录内容
            return {
              name: file,
              path: filePath,
              size: size,
              isDirectory,
              // 如果是目录，假设它有子项(实际内容将在展开时加载)
              hasChildren: isDirectory
            };
          } catch (error) {
            return {
              name: file,
              path: filePath,
              size: 0,
              isDirectory: false,
              hasChildren: false
            };
          }
        })
      );

      // 排序结果 - 目录优先
      return children.sort((a, b) => {
        if (a.isDirectory && !b.isDirectory) return -1;
        if (!a.isDirectory && b.isDirectory) return 1;
        return a.name.localeCompare(b.name);
      });
    } catch (error) {
      console.error(`读取目录内容失败: ${dirPath}`, error);
      return [];
    }
  }

  /**
   * 递归删除指定目录
   */
  public static async deleteDirectory(dirPath: string): Promise<void> {
    try {
      await fs.remove(dirPath);
    } catch (error) {
      throw new Error(`删除目录 ${dirPath} 失败: ${error}`);
    }
  }

}
